package cn.muqingfeng.bbs.ui;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.TextView;
import cn.muqingfeng.bbs.R;
import cn.muqingfeng.bbs.ui.widget.ClipImageView;
import cn.muqingfeng.util.BitmapUtil;
import cn.muqingfeng.util.FileUtil;
import cn.muqingfeng.util.ImageUtil;

public class AvatarPickerActivity extends Activity {
	public static final String BasePhotoUrlDiskCached = FileUtil.getCacheDir().getAbsolutePath();
	private static final String TAG = AvatarPickerActivity.class.getSimpleName();
	public static final String EXTRA_CROP = "_crop";
	public static String TEMP_FILE_NAME = "avatar%d.jpg";
	private AlertDialog progressDialog;
	private boolean crop = true;
	private String pickWay = null; // 照片选取方式: TAKE/PICK;
	private String imgCachePath = BasePhotoUrlDiskCached;
	private String pathTmpImage = null;
	private String pathPhotoTaked = null;
	private String pathCropperImage = null; // 剪辑后的头像图片存放路径;
	private Bitmap croppedImage; // 剪辑后的bitmap;
	private Bitmap initialImage; // 原始bitmap;
	private String albumName; // 带回去的相册名称;
	private TextView tvCancel;
	private TextView tvRetakePhoto;
	private TextView tvUseThisCropperPhoto;
	private ClipImageView civCropperPreview;
	private int mScreenWidth;
	private int mScreenHeight;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		TEMP_FILE_NAME = String.format(TEMP_FILE_NAME, System.currentTimeMillis());
		setContentView(R.layout.avatar_picker);
		DisplayMetrics dm = new DisplayMetrics();
		crop = getIntent().getBooleanExtra(EXTRA_CROP, true);
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		mScreenWidth = dm.widthPixels;
		mScreenHeight = dm.heightPixels;
		tvCancel = (TextView) findViewById(R.id.tv_cancel);
		tvRetakePhoto = (TextView) findViewById(R.id.tv_retakephoto);
		tvUseThisCropperPhoto = (TextView) findViewById(R.id.tv_use_this_cropper_photo);
		civCropperPreview = (ClipImageView) findViewById(R.id.civ_cropper_preview);

		findViewById(R.id.tv_cancel).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (initialImage != null) {
					initialImage.recycle();
				}
				civCropperPreview.setImageBitmap(null);
				startImageLocalPickActivity();
			}
		});
		findViewById(R.id.tv_retakephoto).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (initialImage != null) {
					initialImage.recycle();
				}
				startImageCaptureActivity();

			}
		});

		findViewById(R.id.tv_use_this_cropper_photo).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 此处获取剪裁后的bitmap
				Bitmap bitmap = civCropperPreview.clip();
				Bitmap resizeBitmap;
				if (bitmap.getWidth() <= 150) {
					resizeBitmap = bitmap;
				} else {
					resizeBitmap = BitmapUtil.scaleTo(bitmap, 150, 150);
				}

				// long now = System.currentTimeMillis();
				// String photoId = String.format("%d.%03d", now/1000,
				// now%1000);
				// String fileName = photoId+ SUFFIX;
				String fileName = TEMP_FILE_NAME;
				pathCropperImage = imgCachePath + "/" + fileName;
				try {
					FileOutputStream out = new FileOutputStream(pathCropperImage);
					// 按原有质量的60%压缩;
					if (resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
						out.flush();
					} else {
						ImageUtil.saveBitmap(resizeBitmap, pathCropperImage);
					}
					out.close();
				} catch (FileNotFoundException e) { // for FileOutputStream;
					e.printStackTrace();
				} catch (IOException e) { // for out.flush & out.close;
					e.printStackTrace();
				}
				ImageUtil.saveBitmap(resizeBitmap, pathCropperImage);
				// 删除拍照的原图;
				// if (pathPhotoTaked != null){
				// new File(pathPhotoTaked).delete();
				// }

				Intent data = new Intent();
				if (pathCropperImage == null) {
					pathCropperImage = "";
				}
				data.putExtra("CropperPhotoPath", pathCropperImage);
				setResult(RESULT_OK, data);
				AvatarPickerActivity.this.finish();
			}
		});

		pickWay = getIntent().getStringExtra("PickWay");
		imgCachePath = getIntent().getStringExtra("ImgCachePath");
		if (imgCachePath == null || imgCachePath.length() <= 0) {
			imgCachePath = BasePhotoUrlDiskCached;
		}

		if (pickWay.equals("TAKE")) { // 拍照方式;
			tvCancel.setVisibility(View.GONE);
			tvRetakePhoto.setVisibility(View.VISIBLE);
			startImageCaptureActivity();
		} else if (pickWay.equals("PICK")) { // 本地相册选取;
			tvRetakePhoto.setVisibility(View.GONE);
			tvCancel.setVisibility(View.VISIBLE);
			startImageLocalPickActivity();
		} else {
			finish();
		}
	}

	private void startImageCaptureActivity() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//		long now = System.currentTimeMillis();
//		String photoId = String.format("%d.%03d", now / 1000, now % 1000);
//		String fileName = photoId + SUFFIX;
		 String fileName = TEMP_FILE_NAME;
		pathTmpImage = imgCachePath + "/" + fileName;
		makeDirs(imgCachePath);
		intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" + pathTmpImage));
		startActivityForResult(intent, 20000);
	}

	private void startImageLocalPickActivity() {
		// Intent i = new Intent(Intent.ACTION_PICK,
		// android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
		Intent i = new Intent(Intent.ACTION_GET_CONTENT).setType("image/*");
		startActivityForResult(i, 20001);
	}

	private void makeDirs(String path) {
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		// 清理bitmap资源;
		if (initialImage != null && !initialImage.isRecycled()) {
			initialImage.recycle();
			initialImage = null;
		}
		if (croppedImage != null && !croppedImage.isRecycled()) {
			croppedImage.recycle();
			croppedImage = null;
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_CANCELED) {
			// 删除拍照的原图;
			if (pathPhotoTaked != null) {
				new File(pathPhotoTaked).delete();
			}

			setResult(RESULT_CANCELED);
			finish();
			return;
		}
		// 根据上面发送过去的请求码来区别
		switch (requestCode) {
		case 20000: // take photo;
			pathPhotoTaked = pathTmpImage;
			break;
		case 20001: // local photo;
			// albumName = data.getStringExtra("albumName");
			// pathTmpImage = data.getStringExtra("photoPath");

			Uri selectedImage = data.getData();
			// String[] filePathColumn = { MediaStore.Images.Media.DATA };
			//
			// Cursor cursor = getContentResolver().query(selectedImage,
			// filePathColumn, null, null, null);
			// cursor.moveToFirst();
			//
			// int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
			// pathTmpImage = cursor.getString(columnIndex);
			// cursor.close();

			pathTmpImage = getPath(this, selectedImage);
			break;
		default:
			break;
		}
		if (crop) {
			tvUseThisCropperPhoto.setEnabled(false);
			new ExtractThumbTask(true, pathTmpImage, 1536, 2048).execute();
		} else {
			Intent intent = new Intent();
			intent.putExtra("CropperPhotoPath", pathTmpImage);
			setResult(RESULT_OK, intent);
			finish();
		}
	}

	/*
	 * 生成缩略图异步Task;
	 * 
	 * @param imageView for scrollView;
	 */
	public class ExtractThumbTask extends AsyncTask<Object, Void, String> {
		String srcImgPath = null, dstImgPath = null;
		int reqWidth = 200, reqHeight = 200;
		boolean showProgressDialog = true;
		Bitmap bmp = null;

		// 传入的宽是小于高的;
		public ExtractThumbTask(boolean showProgressDialog, String srcImgPath, int width, int height) {
			this.showProgressDialog = showProgressDialog;
			this.reqWidth = width;
			this.reqHeight = height;
			this.srcImgPath = srcImgPath;
		}

		protected void onPreExecute() {
			// 启动一个转圈等待进度对话框;
			if (showProgressDialog) {
				progressDialog = new AlertDialog.Builder(AvatarPickerActivity.this).setCancelable(false).create();
				progressDialog.setCanceledOnTouchOutside(false);
				progressDialog.show();
			}
		}

		@Override
		protected String doInBackground(Object... params) {
			// long now = System.currentTimeMillis();
			// String photoId = String.format("%d.%03d", now/1000, now%1000);
			// String dstFileName = photoId+ SUFFIX;
			String dstFileName = TEMP_FILE_NAME;
			dstImgPath = imgCachePath + "/" + dstFileName;
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
			// 获取这个图片的宽和高，注意此处的bitmap为null
			BitmapFactory.decodeFile(srcImgPath, options);
			int w = options.outWidth; // 图像实际宽度;
			int h = options.outHeight; // 图像实际高度;
			int newW = w, newH = h; // 需要转换的新尺寸;
			float ratio = 1;
			if (w <= h) { // 纵向图片;
				ratio = Math.max((float) w / reqWidth, (float) h / reqHeight);
			} else { // 横向图片;
				ratio = Math.max((float) h / reqWidth, (float) w / reqHeight);
			}

			if (ratio < 1.0f) { // 图像比缩放请求的要小;用源图;
				// Calculate inSampleSize
				ratio = 1;
			}
			newW = (int) (w / ratio);
			newH = (int) (h / ratio);

			// Decode bitmap with inSampleSize set
			options.inJustDecodeBounds = false;
			options.inSampleSize = ImageUtil.calculateInSampleSize(options, mScreenWidth / 2, mScreenHeight / 2);
			// 读出bmp;
			bmp = BitmapFactory.decodeFile(srcImgPath, options);
			if (ratio > 1.0f) { // 只有图像比请求缩放的宽高要大的时候才需要进行缩放;
				bmp = ImageUtil.zoomBitmap(bmp, newW, newH); // 缩放;
			}
			return dstImgPath;
		}

		@Override
		protected void onPostExecute(String thumbFullPath) {
			if (showProgressDialog) {
				progressDialog.dismiss();
			}
			tvUseThisCropperPhoto.setEnabled(true);
			civCropperPreview.setImageBitmap(bmp);
			initialImage = bmp;
		}
	}

	/**
	 * Get a file path from a Uri. This will get the the path for Storage Access
	 * Framework Documents, as well as the _data field for the MediaStore and
	 * other file-based ContentProviders.
	 * 
	 * @param context
	 *            The context.
	 * @param uri
	 *            The Uri to query.
	 * @author paulburke
	 */
	@TargetApi(Build.VERSION_CODES.KITKAT)
	public static String getPath(final Context context, final Uri uri) {

		final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

		// DocumentProvider
		if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
			// ExternalStorageProvider
			if (isExternalStorageDocument(uri)) {
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				if ("primary".equalsIgnoreCase(type)) {
					return Environment.getExternalStorageDirectory() + "/" + split[1];
				}

				// TODO handle non-primary volumes
			}
			// DownloadsProvider
			else if (isDownloadsDocument(uri)) {

				final String id = DocumentsContract.getDocumentId(uri);
				final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

				return getDataColumn(context, contentUri, null, null);
			}
			// MediaProvider
			else if (isMediaDocument(uri)) {
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				Uri contentUri = null;
				if ("image".equals(type)) {
					contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
				} else if ("video".equals(type)) {
					contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
				} else if ("audio".equals(type)) {
					contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
				}

				final String selection = "_id=?";
				final String[] selectionArgs = new String[] { split[1] };

				return getDataColumn(context, contentUri, selection, selectionArgs);
			}
		}
		// MediaStore (and general)
		else if ("content".equalsIgnoreCase(uri.getScheme())) {
			return getDataColumn(context, uri, null, null);
		}
		// File
		else if ("file".equalsIgnoreCase(uri.getScheme())) {
			return uri.getPath();
		}

		return null;
	}

	/**
	 * Get the value of the data column for this Uri. This is useful for
	 * MediaStore Uris, and other file-based ContentProviders.
	 * 
	 * @param context
	 *            The context.
	 * @param uri
	 *            The Uri to query.
	 * @param selection
	 *            (Optional) Filter used in the query.
	 * @param selectionArgs
	 *            (Optional) Selection arguments used in the query.
	 * @return The value of the _data column, which is typically a file path.
	 */
	public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {

		Cursor cursor = null;
		final String column = "_data";
		final String[] projection = { column };

		try {
			cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
			if (cursor != null && cursor.moveToFirst()) {
				final int column_index = cursor.getColumnIndexOrThrow(column);
				return cursor.getString(column_index);
			}
		} finally {
			if (cursor != null)
				cursor.close();
		}
		return null;
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is ExternalStorageProvider.
	 */
	public static boolean isExternalStorageDocument(Uri uri) {
		return "com.android.externalstorage.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is DownloadsProvider.
	 */
	public static boolean isDownloadsDocument(Uri uri) {
		return "com.android.providers.downloads.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is MediaProvider.
	 */
	public static boolean isMediaDocument(Uri uri) {
		return "com.android.providers.media.documents".equals(uri.getAuthority());
	}
}
